package bcslib

import (
	"errors"
	"github.com/go-xorm/xorm"
	"lpaiche.com/bailconsumer/bcslib/model"
	u "lpaiche.com/utils"
	"strconv"
	"time"
)

type BailFixed struct {
	Xt      *u.XormTrans
	session *xorm.Session
}

//获取一个保证金持久化对象
func NewBailFixed() (bf *BailFixed) {
	bf = new(BailFixed)
	bf.initSession()
	return bf
}

func (bf *BailFixed) initSession() {
	bf.Xt = u.NewXormTrans()
	session := bf.Xt.GetCurrentXormSession()
	bf.session = session
}

//执行保证金操作队列内容
func (bf *BailFixed) ExecBailQueueContext(bqc *BailQueueContext) (id int64) {
	bf.Xt.NewBegin()
	dealer_id := strconv.FormatInt(bqc.Summary.Dealer_id, 10)
	handingKey := conf.RedisKeys.BailChangeQueueHanding
	handingKey = handingKey + dealer_id

	//使用事务操作
	var err error

	t := bqc.Log.Use_type
	switch t {
	case 1:
		id, err = bf.execAddBail(bqc)
	case 2:
		id, err = bf.execFreezeBail(bqc)
	case 3:
		id, err = bf.execUnFreezeBail(bqc)
	case 4, 8:
		id, err = bf.execDecBail(bqc)
	case 5, 6:
		id, err = bf.execDeductBail(bqc)
	default:
		err = errors.New("不能识别的保证金操作类型！")
	}

	//保存保证金概要
	_, err = bf.save2BailSummary(bqc)

	//time.Sleep(1 * time.Second)

	if err != nil {
		//回滚
		bf.Xt.Rollback()
		u.Panic(err)
	} else {
		//提交事务
		bf.Xt.Commit()
	}
	return id
}

//关闭会话
func (bf *BailFixed) Close() {
	bf.Xt.CloseSession()
}

//BailQueueContext转正AuDealerBailLog
func (bf *BailFixed) bqc2BailLog(bqc *BailQueueContext) *AuDealerBailLog {
	dbl := new(AuDealerBailLog)
	dbl.BlId = 0
	dbl.DealerId = bqc.Log.Dealer_id
	dbl.OrderId = bqc.Log.Order_id
	dbl.UseTime = bqc.Log.Use_time
	dbl.UseType = bqc.Log.Use_type
	dbl.UseDetail = bqc.Log.Use_detail
	dbl.OccurMoney = bqc.Log.Occur_money
	dbl.RemainAmount = bqc.Log.Remain_amount
	dbl.RechargeMethod = bqc.Log.Recharge_method
	dbl.RechargeNo = bqc.Log.Recharge_no
	dbl.Createtime = time.Now().Local().Format("2006-01-02 15:04:05")
	dbl.FreeBlId = bqc.Log.Free_bl_id
	dbl.IsFree = bqc.Log.Is_free
	dbl.RechargeId = bqc.Log.Recharge_id
	dbl.CollectionId = bqc.Log.Collection_id
	dbl.PaymentId = bqc.Log.Payment_id
	return dbl
}

//保存BailSummary
func (bf *BailFixed) save2BailSummary(bqc *BailQueueContext) (b bool, err error) {
	if bqc.Summary.Dealer_id == 0 {
		return false, errors.New("保存车商概要，dealer_id不可以为空")
	}
	sql := "UPDATE au_car_dealer SET `bail_amount`=?,`freeze_amount`=?,`indemnity_amount`=? WHERE dealer_id=?"
	res, err := bf.session.Exec(sql, bqc.Summary.Bail_amount, bqc.Summary.Freeze_amount, bqc.Summary.Indemnity_amount, bqc.Summary.Dealer_id)
	if err != nil {
		return false, err
	}
	n, _ := res.RowsAffected()
	if n > 0 {
		return true, nil
	} else {
		return false, nil
	}
}

//获得车商拍单保证金冻结记录
func (bf *BailFixed) getAuDealerBailLog(dealer_id string, order_id string) (dbl *AuDealerBailLog) {
	freeLogs := make([]AuDealerBailLog, 0)
	err := bf.session.Where("`order_id`=? and `dealer_id`=? and `use_type`=2 and `is_free`=0", order_id, dealer_id).Limit(1, 0).Find(&freeLogs)
	if err != nil {
		u.Panic(err)
	}
	if len(freeLogs) < 1 {
		err = errors.New("未发现保证金冻结记录!")
		u.Panic(err)
		return dbl
	} else {
		u.Trace("找到冻结记录 dealer_id:" + dealer_id + " order_id:" + order_id)
		u.Trace(freeLogs[0])
		return &freeLogs[0]
	}
}

func (bf *BailFixed) GetInsertID() (id int64) {
	r, err := bf.session.Query("select last_insert_id() as ID")
	if err != nil {
		u.Panic(err)
	}
	if len(r) > 0 {
		id, _ = strconv.ParseInt(string(r[0]["ID"]), 10, 64)
		return id
	} else {
		return 0
	}
}

//执行充值 1
func (bf *BailFixed) execAddBail(bqc *BailQueueContext) (id int64, err error) {
	dbl := bf.bqc2BailLog(bqc)
	n, err := bf.session.InsertOne(dbl)
	if err != nil {
		return 0, err
	}
	if !(n > 0) {
		return 0, errors.New("充值保证金,插入记录失败!")
	}
	id = bf.GetInsertID()
	return id, nil
}

//保证金提取 4,8
func (bf *BailFixed) execDecBail(bqc *BailQueueContext) (id int64, err error) {
	dbl := bf.bqc2BailLog(bqc)
	n, err := bf.session.InsertOne(dbl)
	if err != nil {
		return 0, err
	}
	if !(n > 0) {
		return 0, errors.New("提取或消费保证金,插入记录失败!")
	}
	id = bf.GetInsertID()
	return id, nil
}

//获得拍单信息
func (bf *BailFixed) getOrder(orderId int64) (order *model.AuOrder) {
	orders := make([]model.AuOrder, 0)
	err := bf.session.Where("`order_id`=?", orderId).Limit(1, 0).Find(&orders)
	if err != nil {
		u.Panic(err)
	}
	order = &orders[0]
	return order
}

//冻结 2
func (bf *BailFixed) execFreezeBail(bqc *BailQueueContext) (id int64, err error) {
	order := bf.getOrder(bqc.Log.Order_id)
	bqc.Log.Use_detail = "对拍品 【" + order.OrderNo + "】 进行出价，冻结保证金。"
	dbl := bf.bqc2BailLog(bqc)
	n, err := bf.session.InsertOne(dbl)
	if err != nil {
		return 0, err
	}
	if !(n > 0) {
		return 0, errors.New("冻结保证金,插入记录失败!")
		return 0, nil
	}
	id = bf.GetInsertID()
	return id, nil
}

//解冻 3
func (bf *BailFixed) execUnFreezeBail(bqc *BailQueueContext) (id int64, err error) {
	order := bf.getOrder(bqc.Log.Order_id)
	bqc.Log.Use_detail = "解冻出价保证金，拍品 【" + order.OrderNo + "】。"
	free_dbl := bf.getAuDealerBailLog(strconv.FormatInt(bqc.Log.Dealer_id, 10), strconv.FormatInt(bqc.Log.Order_id, 10))
	free_bl_id := free_dbl.BlId
	//插入记录
	dbl := bf.bqc2BailLog(bqc)
	dbl.FreeBlId = int64(free_bl_id)
	n, err := bf.session.InsertOne(dbl)
	if err != nil {
		return 0, err
	}
	if !(n > 0) {
		return 0, errors.New("解冻保证金,插入记录失败!")
		return 0, nil
	}
	id = bf.GetInsertID()
	//更新
	sql := "UPDATE au_dealer_bail_log SET `is_free`=? WHERE bl_id=?"
	_, err = bf.session.Exec(sql, 1, free_bl_id)
	if err != nil {
		return 0, err
	}
	return id, nil
}

//从冻结扣除 5,6
func (bf *BailFixed) execDeductBail(bqc *BailQueueContext) (id int64, err error) {
	order := bf.getOrder(bqc.Log.Order_id)
	bqc.Log.Use_detail = "违约扣款，扣除违约保证金，拍单 【" + order.OrderNo + "】。"
	free_dbl := bf.getAuDealerBailLog(strconv.FormatInt(bqc.Log.Dealer_id, 10), strconv.FormatInt(bqc.Log.Order_id, 10))
	free_bl_id := free_dbl.BlId
	//插入记录
	dbl := bf.bqc2BailLog(bqc)
	dbl.FreeBlId = int64(free_bl_id)
	n, err := bf.session.InsertOne(dbl)
	if err != nil {
		return 0, err
	}
	if !(n > 0) {
		return 0, errors.New("扣除保证金,插入记录失败!")
	}
	id = bf.GetInsertID()
	return id, nil
}
